package cn.hzc.fortess.system.service;

import cn.hzc.fortess.config.properties.SamProperties;
import cn.hzc.fortess.core.common.constant.JwtConstants;
import cn.hzc.fortess.core.util.JwtTokenUtil;
import cn.hzc.fortess.system.common.EnableStatus;
import cn.hzc.fortess.system.dao.JwtUserTokenDao;
import cn.hzc.fortess.system.dao.UserDao;
import cn.hzc.fortess.system.entity.JwtUserToken;
import cn.hzc.fortess.system.page.Pagination;
import cn.hzc.fortess.system.search.ApiTokenSearch;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;

@Service
public class JwtTokenServiceImpl implements JwtTokenService {

    private final static String JWT_USER_TOKEN = "jwt:token:userid-%s";

    @Autowired
    JwtUserTokenDao jwtUserTokenDao;
    @Autowired
    UserDao userDao;
    @Autowired
    SamProperties samProperties;

    private static String getJwtUserTokenSessionKey(Integer userId) {
        return String.format(JWT_USER_TOKEN, userId);
    }

    @Override
    public String getJwtToken(HttpServletRequest request, Integer userId) {
        if (request.getSession() == null) {
            return null;
        }
        Object obj = request.getSession().getAttribute(getJwtUserTokenSessionKey(userId));
        if (obj != null) {
            return obj.toString();
        }
        return null;
    }

    //
    @Override
    public void generate(HttpServletRequest request, Integer userId) {

        removeJwtToken(userId);
//        JwtUserToken jwtUserToken = jwtUserTokenDao.findToKenByUserId(userId);
//        if (jwtUserToken != null && jwtUserToken.getLiveTime() > System.currentTimeMillis()) {
//            request.getSession().setAttribute(getJwtUserTokenSessionKey(userId), jwtUserToken.getUserToken());
//        } else {
        final Long liveTime = System.currentTimeMillis() + JwtConstants.EXPIRATION;
        final String token = JwtTokenUtil.generateToken(String.valueOf(userId), liveTime);
        saveToken(userId, token, null, liveTime);
        request.getSession().setAttribute(getJwtUserTokenSessionKey(userId), token);
        // }
    }

    @Override
    public String generateJwtToken(Integer userId) {

        removeJwtToken(userId);

        final Long liveTime = System.currentTimeMillis() + JwtConstants.EXPIRATION;
        final String token = JwtTokenUtil.generateToken(String.valueOf(userId), liveTime);
        saveToken(userId, token, null, liveTime);
        return token;
    }

    private void saveToken(Integer userId, String token, String refreshToken, Long liveTime) {
        JwtUserToken bean = new JwtUserToken();
        bean.setUserToken(token);
        bean.setRefreshToken(refreshToken);
        bean.setUserId(userId);
        bean.setLiveTime(liveTime);
        bean.setCreateTime(new Date());
        bean.setStatus(EnableStatus.ENABLE.getStatus());
        bean.setAccount(userDao.findById(userId).getAccount());
        jwtUserTokenDao.insert(bean);
    }

    @Override
    public boolean isTokenExpired(String token) {
        if (StringUtils.isBlank(token)) {
            return true;
        }
        if (JwtTokenUtil.isTokenExpired(token)) {
            return true;
        }
        JwtUserToken jwtToken = jwtUserTokenDao.findToKenByUserId(Integer.parseInt(JwtTokenUtil.getUserIdFromToken(token)));
        if (jwtToken == null || (!token.equals(jwtToken.getUserToken()))) {
            return true;
        }
        return false;
    }

    @Override
    public void removeJwtToken(Integer userId) {
        if (userId == null) {
            return;
        }
        jwtUserTokenDao.updateUsed(userId);
    }


    @Override
    public int cleanExpired() {
       return  jwtUserTokenDao.deleteExpired(System.currentTimeMillis());
    }

    @Override
    public Pagination page(ApiTokenSearch search) {
        Pagination pagination = new Pagination();
        pagination.setCount(jwtUserTokenDao.count(search));
        if (pagination.getCount() > 0) {
            List<JwtUserToken> tokens = jwtUserTokenDao.page(search);
            tokens.parallelStream().forEach(jwtUserToken -> {
                if (jwtUserToken.getLiveTime() <= System.currentTimeMillis()) {
                    jwtUserToken.setStatus(EnableStatus.DISABLE.getStatus());
                }
            });
            pagination.setData(tokens);
        }
        return pagination;
    }

    @Override
    public int delete(Integer id) {
        return jwtUserTokenDao.delete(id);
    }

}
